﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Documents;
using System.IO;
using System.Collections;
using System.Data;
using DotNetMatrix;
using MathNet.Numerics.LinearAlgebra.Double;
namespace stata
{
    public class Operations
    {
        public DataTable dt;
        public Operations()
        {
            dt = new DataTable();
        }
        public int wczytajnazwy(string sciezka)
        {
            FileStream fileStream = new FileStream(sciezka, FileMode.Open, FileAccess.Read);

            int length = (int)fileStream.Length;  // get file length

            int count = 0;                            // actual number of bytes read

            int sum = 0;                          // total number of bytes read

            int readthis = 1;

            byte[] buffer = new byte[1];

            string s = "";
            int i = 0;
            int j = 1;
            while (i != 1 || j != 1)
            {
                j = 1;
                int sumw = 0;
                while (buffer[0] != 10)
                {
                    count = fileStream.Read(buffer, 0, readthis);
                    sum++;
                    if (sumw == 0 && buffer[0] == 10)
                    {
                        j = 0;
                    }
                    else
                    {
                        if ((char)buffer[0] == ',')
                        {
                            buffer[0] = (byte)'\t';
                        }
                        if (((char)buffer[0] != '#' && j == 1))
                        {
                            if ((char)buffer[0] != '\t' && buffer[0] != 10 && (char)buffer[0] != '\r')
                            {
                                s += (char)buffer[0];
                            }
                            else if (s != "")
                            {
                                dt.Columns.Add(s);
                                s = "";
                            }
                        }
                        else
                        {
                            j = 0;
                        }
                    }
                    i = 1;
                    sumw++;
                }
                buffer[0] = 0;
            }
            return sum;
        }
        public int stworzkolumny(string sciezka)
        {
            FileStream fileStream = new FileStream(sciezka, FileMode.Open, FileAccess.Read);

            int length = (int)fileStream.Length;  // get file length
            int licz = 1;

            int count = 0;                            // actual number of bytes read

            int sum = 0;                          // total number of bytes read

            int readthis = 1;

            byte[] buffer = new byte[1];

            string s = "";
            int i = 0;
            int j = 1;
            while (i != 1 || j != 1)
            {
                j = 1;
                int sumw = 0;
                while (buffer[0] != 10)
                {
                    count = fileStream.Read(buffer, 0, readthis);
                    sum++;
                    if ((sumw == 0 && buffer[0] == 10) || (sumw == 0 && buffer[0] == 13))
                    {
                        j = 0;
                    }
                    else
                    {
                        if (((char)buffer[0] != '#' && j == 1))
                        {
                            if ((char)buffer[0] != '\t' && buffer[0] != 10 && (char)buffer[0] != '\r')
                            {
                                s += (char)buffer[0];
                            }
                            else if (s != "")
                            {
                                dt.Columns.Add(licz.ToString());
                                licz++;
                                s = "";
                            }
                        }
                        else
                        {
                            j = 0;
                        }

                    }
                    i = 1;
                    sumw++;
                }
                buffer[0] = 0;
            }
            return sum;
        }

        public int wczytajdane(string sciezka, int first)
        {
            FileStream fileStream = new FileStream(sciezka, FileMode.Open, FileAccess.Read);

            int length = (int)fileStream.Length;

            int count = 0;

            int sum2 = 0;

            int readthis = 1;

            byte[] buffer = new byte[1];

            string s = "";
            int i = 0;
            int j = 1;
            while (i < fileStream.Length)
            {
                String[] pom = new String[dt.Columns.Count];
                int pp = 0;
                while (buffer[0] != 10 && i < fileStream.Length)
                {
                    fileStream.Read(buffer, 0, readthis);
                    i++;
                    sum2++;
                    if (sum2 > first)
                    {
                        if ((char)buffer[0] != '#' && j == 1)
                        {
                            if ((char)buffer[0] != '\t' && buffer[0] != 10 && (char)buffer[0] != '\r')
                            {

                                if (s == "" && (char)buffer[0] == ',')
                                {
                                    s += "0";
                                }
                                s += (char)buffer[0];
                            }
                            else if (s != "")
                            {
                                if (s != "")
                                {
                                    pom[pp] = s;
                                    pp++;
                                }
                                s = "";
                            }
                            if (i == fileStream.Length && s != "")
                            {
                                pom[pp] = s;
                            }
                        }
                        else
                        {
                            j = 0;
                        }
                    }
                }
                j = 1;
                buffer[0] = 0;
                int g = 0;
                for (int ii = 0; ii < dt.Columns.Count; ii++)
                {
                    if (pom[ii] == null)
                    {
                        g = 1;
                    }
                }
                if (g == 0)
                    dt.Rows.Add(pom);
            }
            return 0;
        }

        public String klasyfikacjaEuklides(List<String> nowy, int klasa, int k, int row)
        {

            List<Odleglosc> odlegl = new List<Odleglosc>();
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                int flaga = 0;
                int z = 0;
                float odl = 0;
                if (i != row)
                {
                    for (int j = 0; j < dt.Columns.Count - 1; j++)
                    {
                        if (j != klasa)
                        {
                            try
                            {

                                String wiersz = dt.Rows[i].Field<String>(j);


                                wiersz = wiersz.Replace('.', ',');

                                if (wiersz != "?")
                                {
                                    float w = float.Parse(wiersz);

                                    String n = nowy[z];
                                    n = n.Replace('.', ',');
                                    float wart = float.Parse(n);
                                    odl += (float)(Math.Pow((w - wart), 2));
                                    z++;
                                }
                                else
                                {
                                    j = dt.Columns.Count;
                                    flaga = 1;
                                }
                            }
                            catch (Exception e)
                            {

                            }
                        }

                    }
                    if (flaga == 0)
                    {
                        odl = (float)Math.Sqrt(odl);
                        Odleglosc od = new Odleglosc(odl, i);
                        odlegl.Add(od);
                    }
                }
            }


            List<String> klasy = new List<string>();

            for (int i = 0; i < k; i++)
            {
                Odleglosc min = odlegl[0];
                for (int j = 0; j < odlegl.Count; j++)
                {
                    if (min.odl > odlegl[j].odl)
                    {
                        min = odlegl[j];
                    }
                }


                klasy.Add(dt.Rows[min.row].Field<String>(klasa));
                odlegl.Remove(min);
            }
            int max = 0;
            String ret = null;
            for (int i = 0; i < klasy.Count; i++)
            {

                String kl = klasy[i];
                int ilosc = 0;
                for (int j = 0; j < klasy.Count; j++)
                {
                    if (klasy[j] == kl)
                    {
                        ilosc++;
                    }
                }
                if (ilosc > max)
                {
                    ret = kl;
                    max = ilosc;
                }
            }
            return ret;
        }
        public String klasyfikacjamanhattan(List<String> nowy, String klasa, int k)
        {
            int ktory = 0;

            for (int i = 0; i < dt.Columns.Count; i++)
            {
                if (dt.Columns[i].ColumnName.Equals(klasa))
                {
                    ktory = i;
                    i = dt.Columns.Count;
                }
            }

            List<float> odlegl = new List<float>();
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                int z = 0;
                float odl = 0;
                for (int j = 0; j < dt.Columns.Count; j++)
                {
                    try
                    {
                        String wiersz = dt.Rows[i].Field<String>(j);

                        wiersz = wiersz.Replace('.', ',');
                        float w = float.Parse(wiersz);
                        String n = nowy[z];

                        n = n.Replace('.', ',');
                        float wart = float.Parse(n);
                        float wartbez = 0;
                        wartbez = w - wart;
                        if (wartbez < 0)
                        {
                            wartbez = -wartbez;

                        }

                        odl += wartbez;
                        z++;


                    }
                    catch (Exception e)
                    {

                    }

                }

                odlegl.Add(odl);
            }



            List<String> klasy = new List<string>();

            for (int i = 0; i < k; i++)
            {
                float min = 9999999999999999999;
                for (int j = 0; j < odlegl.Count; j++)
                {
                    if (min > odlegl[j])
                    {
                        min = odlegl[j];
                    }
                }


                klasy.Add(dt.Rows[odlegl.IndexOf(min)].Field<String>(ktory));
                odlegl.Remove(min);
            }
            int max = 0;
            String ret = null;
            for (int i = 0; i < klasy.Count - 1; i++)
            {

                String kl = klasy[i];
                int ilosc = 0;
                for (int j = 0; j < klasy.Count; j++)
                {
                    if (klasy[j] == kl)
                    {
                        ilosc++;
                    }
                }
                if (ilosc > max)
                {
                    ret = kl;
                    max = ilosc;
                }
            }



            return ret;
        }

        public int poprawnoscManhattan(int k, String klasa)
        {
            float poprawne = 0;
            int ktory = 0;

            for (int i = 0; i < dt.Columns.Count; i++)
            {
                if (dt.Columns[i].ColumnName.Equals(klasa))
                {
                    ktory = i;
                    i = dt.Columns.Count;
                }
            }

            for (int i = 0; i < dt.Rows.Count; i++)
            {
                List<String> nowy = new List<string>();
                for (int j = 0; j < dt.Columns.Count; j++)
                {
                    try
                    {
                        String wiersz = dt.Rows[i].Field<String>(j);
                        wiersz = wiersz.Replace('.', ',');
                        float w = float.Parse(wiersz);

                        nowy.Add(wiersz);
                    }
                    catch (Exception e)
                    {

                    }
                }
                string kl = klasyfikacjamanhattan(nowy, klasa, k);
                if (kl == dt.Rows[i].Field<String>(ktory))
                {
                    poprawne++;
                }
            }
            int procent = (int)((poprawne / dt.Rows.Count) * 100);
            return procent;
        }
        public double Abs(int classColumn, int columnNumber, int rowNumber)
        {
            String cls = dt.Rows[rowNumber].Field<String>(classColumn);
            double rowsCount = 0;
            double sum = 0;
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                if (dt.Rows[i].Field<String>(classColumn).Equals(cls) && !dt.Rows[i].Field<String>(columnNumber).Equals("?"))
                {
                    sum += Double.Parse(dt.Rows[i].Field<String>(columnNumber));
                    rowsCount++;
                }
            }
            double wyn = (double)(sum / rowsCount);
            return wyn;
        }
        public int Abs2(int classColumn, DataTable dt, int rowNumber, int columnNumber)
        {
            String cls = dt.Rows[rowNumber].Field<String>(classColumn);
            double rowsCount = 0;
            double sum = 0;
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                if (dt.Rows[i].Field<String>(classColumn).Equals(cls) && !dt.Rows[i].Field<String>(columnNumber).Equals("?"))
                {
                    sum += Double.Parse(dt.Rows[i].Field<String>(columnNumber));
                    rowsCount++;
                }
            }
            int wyn = (int)(sum / rowsCount);
            return wyn;
        }
        public DataTable Transponowanie(DataTable dt)
        {
            DataTable pomdt = new DataTable();
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                pomdt.Columns.Add(i.ToString());
            }
            for (int j = 0; j < dt.Columns.Count; j++)
            {
                string[] tab = new string[pomdt.Columns.Count];
                pomdt.Rows.Add(tab);
            }

            for (int i = 0; i < pomdt.Columns.Count; i++)
            {
                for (int j = 0; j < pomdt.Rows.Count; j++)
                {
                    pomdt.Rows[j].SetField<string>(i, dt.Rows[i].Field<string>(j));

                }
            }
            return pomdt;
        }
        public DataTable MnożenieMacierzy(DataTable dtT, DataTable dt)
        {
            DataTable pomdt = new DataTable();

            for (int i = 0; i < dt.Columns.Count; i++)
            {
                pomdt.Columns.Add((i + 1).ToString());
            }
            for (int i = 0; i < dtT.Rows.Count; i++)
            {
                string[] tab = new string[pomdt.Columns.Count];
                pomdt.Rows.Add(tab);
            }
            for (int i = 0; i < pomdt.Columns.Count; i++)
            {
                for (int j = 0; j < pomdt.Rows.Count; j++)
                {
                    string[] tabT = new string[dtT.Columns.Count];
                    string[] tab = new string[dt.Rows.Count];
                    for (int ii = 0; ii < dtT.Columns.Count; ii++)
                    {
                        tabT[ii] = dtT.Rows[j].Field<string>(ii);
                    }
                    for (int ii = 0; ii < dt.Rows.Count; ii++)
                    {
                        tab[ii] = dt.Rows[ii].Field<string>(i);
                    }
                    Decimal wyn = 0;
                    for (int x = 0; x < tab.Length; x++)
                    {
                        wyn += (Decimal.Parse(tab[x]) * Decimal.Parse(tabT[x]));
                    }
                    pomdt.Rows[j].SetField<string>(i, wyn.ToString());

                }
            }
            return pomdt;
        }
        public DataTable wartWlasneMac(DataTable dt)
        {
            Console.WriteLine("macierz matrix:");
            double[,] matrix = new double[dt.Columns.Count, dt.Rows.Count];
            for (int i = 0; i < dt.Columns.Count; i++)
            {
                for (int j = 0; j < dt.Rows.Count; j++)
                {
                    matrix[i, j] = double.Parse(dt.Rows[j].Field<string>(i));
                    Console.WriteLine(dt.Rows[j].Field<string>(i));
                }
            }
            Double[][] d = new Double[dt.Rows.Count][];
            Console.WriteLine("driga macierz d:");
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                double[] drow = new double[dt.Rows.Count];
                for (int j = 0; j < dt.Rows.Count; j++)
                {
                    drow[j] = matrix[i, j];
                    Console.WriteLine(matrix[i, j]);
                }
                d[i] = drow;
            }
            GeneralMatrix result = new GeneralMatrix(d, dt.Rows.Count, dt.Rows.Count);
            EigenvalueDecomposition E = new EigenvalueDecomposition(result);
            DataTable pomdt = new DataTable();
            for (int i = 0; i < dt.Columns.Count; i++)
            {
                pomdt.Columns.Add(i.ToString());
            }
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                string[] tab = new string[pomdt.Columns.Count];
                for (int j = 0; j < dt.Columns.Count; j++)
                {
                    tab[j] = 0.ToString();
                }
                pomdt.Rows.Add(tab);
            }
            double[] eigenvalues = E.RealEigenvalues;
            Array.Sort(eigenvalues);
            int k = eigenvalues.Length - 1;
            for (int i = 0; i < dt.Columns.Count; i++)
            {
                string s = eigenvalues[k].ToString();
                Decimal dec = (Decimal)eigenvalues[k];
                Decimal dec2 = Math.Round(dec, 4);

                pomdt.Rows[i].SetField<string>(i, dec2.ToString());
                k--;
            }
            return pomdt;

        }

        public DataTable getWMatrix(DataTable sigma, int rows, int columns)
        {
            DataTable pomdt = new DataTable();
            double[] r = new double[columns];
            for (int i = 0; i < columns; i++)
            {
                r[i] = 0;
            }
            for (int i = 0; i < columns; i++)
            {
                pomdt.Columns.Add(i.ToString());
            }
            for (int i = 0; i < rows; i++)
            {
                pomdt.Rows.Add(r);
            }
            for (int i = 0; i < sigma.Columns.Count; i++)
            {
                for (int j = 0; j < sigma.Rows.Count; j++)
                {
                    pomdt.Rows[j].SetField<string>(i, sigma.Rows[j].Field<string>(i));
                }
            }
            return pomdt;

        }
        public DataTable sqrtWartWlas(DataTable dt)
        {
            DataTable pomdt = new DataTable();
            for (int i = 0; i < dt.Columns.Count; i++)
            {
                pomdt.Columns.Add(i.ToString());
            }
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                double[] row = new double[dt.Columns.Count];
                pomdt.Rows.Add(row);
            }
            for (int i = 0; i < dt.Columns.Count; i++)
            {
                for (int j = 0; j < dt.Rows.Count; j++)
                {
                    pomdt.Rows[j].SetField<string>(i, dt.Rows[j].Field<string>(i));
                }
            }
            for (int i = 0; i < dt.Columns.Count; i++)
            {
                for (int j = 0; j < dt.Rows.Count; j++)
                {
                    if (dt.Rows[j].Field<string>(i) != "0")
                    {
                        double wart = Math.Sqrt(double.Parse(dt.Rows[j].Field<string>(i)));
                        pomdt.Rows[j].SetField<string>(i, wart.ToString());
                    }
                }
            }
            return pomdt;
        }
        public DataTable Uatrix(DataTable Bdt)
        {

            double[,] matrix = new double[Bdt.Columns.Count, Bdt.Rows.Count];
            for (int i = 0; i < Bdt.Columns.Count; i++)
            {
                for (int j = 0; j < Bdt.Rows.Count; j++)
                {

                    matrix[i, j] = double.Parse(Bdt.Rows[j].Field<string>(i));
                }
            }
            Double[][] d = new Double[Bdt.Columns.Count][];

            for (int i = 0; i < Bdt.Columns.Count; i++)
            {
                double[] drow = new double[Bdt.Rows.Count];
                for (int j = 0; j < Bdt.Rows.Count; j++)
                {
                    drow[j] = matrix[i, j];
                }
                d[i] = drow;
            }

            GeneralMatrix result = new GeneralMatrix(d, Bdt.Columns.Count, Bdt.Rows.Count);
            EigenvalueDecomposition E = new EigenvalueDecomposition(result);
            GeneralMatrix V = E.GetV();
         


            double[][] v = V.Array;
            Console.WriteLine(V.Array.ToString());
            DataTable pomdt = new DataTable();
            for (int i = 0; i < Bdt.Columns.Count; i++)
            {
                pomdt.Columns.Add(i.ToString());
            }
            string[] tabs = new string[Bdt.Columns.Count];
            for (int i = 0; i < Bdt.Rows.Count; i++)
            {
                pomdt.Rows.Add(tabs);
            }
            for (int i = 0; i < Bdt.Rows.Count; i++)
            {

                double[] tab = v[i].ToArray<double>();
               
                int k = 0;
                for (int j = tab.Length-1; j >= 0; j--)
                {
                    pomdt.Rows[i].SetField<string>(k, tab[j].ToString());
                    k++;
                }
            }
            return pomdt;
        }

        public DataTable Vmatrix(DataTable dt, DataTable U, DataTable sig)
        {
            DataTable Vdt = new DataTable();
            for (int i = 0; i < dt.Columns.Count; i++)
            {
                Vdt.Columns.Add(i.ToString());
            }
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                string[] tab = new string[dt.Columns.Count];
                Vdt.Rows.Add(tab);
            }
            DataTable upomdt = new DataTable();
            upomdt.Columns.Add("1");
            for (int i = 0; i < U.Rows.Count; i++)
            {
                upomdt.Rows.Add(U.Rows[i].Field<string>(0));

            }
            int lastcolumn = 0;
            int y = 0;
            for (int i = 0; i < Vdt.Columns.Count; i++)
            {
                if (i < sig.Rows.Count && y<U.Columns.Count)
                {
                    for (int j = 0; j < U.Rows.Count; j++)
                    {
                        upomdt.Rows[j].SetField<string>(0, U.Rows[j].Field<string>(y));
                    }
                    DataTable pom = this.MnożenieMacierzy(dt, upomdt);
                    y++;
                    if (sig.Rows[i].Field<string>(i) != "0")
                    {
                        for (int h = 0; h < Vdt.Rows.Count; h++)
                        {
                            Vdt.Rows[h].SetField<string>(i, (double.Parse(pom.Rows[h].Field<string>(0)) / double.Parse(sig.Rows[i].Field<string>(i))).ToString());
                            Console.WriteLine((double.Parse(pom.Rows[h].Field<string>(0))));
                        }
                    }
                    else
                    {
                        double[] row = OrtogonalizacjaGramaSchmidta(Vdt, lastcolumn, i);

                        double norma = 0;
                        for (int l = 0; l < row.Length; l++)
                        {
                            norma += Math.Pow(row[l], 2);
                        }
                        norma = Math.Sqrt(norma);
                        if (norma != 1)
                        {
                            for (int l = 0; l < row.Length; l++)
                            {
                                row[l] /= norma;
                            }
                        }
                        for (int k = 0; k < Vdt.Rows.Count; k++)
                        {
                            Vdt.Rows[k].SetField<string>(i, row[k].ToString());
                        }
                        lastcolumn++;
                    }
                }
                else
                {
                    double[] row = OrtogonalizacjaGramaSchmidta(Vdt, lastcolumn, i);
                    double norma = 0;
                    for (int l = 0; l < row.Length; l++)
                    {
                        norma += Math.Pow(row[l], 2);
                    }
                    norma = Math.Sqrt(norma);
                    if (norma != 1)
                    {
                        for (int l = 0; l < row.Length; l++)
                        {
                            row[l] /= norma;
                        }
                    }
                    for (int k = 0; k < Vdt.Rows.Count; k++)
                    {
                        Vdt.Rows[k].SetField<string>(i, row[k].ToString());
                    }
                    lastcolumn++;
                }

            }

            return Vdt;
        }

        public void test(DataTable dt)
        {
            DataTable Tsvd1 = this.Transponowanie(dt);
            Console.WriteLine("po transponowaniu");
            DataTable B1dt = this.MnożenieMacierzy(Tsvd1, dt);
            DataTable B1dt2 = this.MnożenieMacierzy(dt, Tsvd1);
            if (this.StopienMacierzy(B1dt) > this.StopienMacierzy(B1dt2))
            {
                B1dt = B1dt2;
            }
            else if (B1dt.Rows.Count > B1dt2.Rows.Count)
            {
                B1dt = B1dt2;
            }
            Console.WriteLine("mam juz b");
            DataTable l1dt = this.wartWlasneMac(B1dt);
            Console.WriteLine("mam juz wartosci wlasne");
            DataTable V1 = this.Uatrix(B1dt);
            Console.WriteLine("mam juz V");
            DataTable sig1 = this.sqrtWartWlas(l1dt);
            Console.WriteLine("mama sigmy");
            DataTable W1 = this.getWMatrix(sig1, dt.Rows.Count, dt.Columns.Count);
            Console.WriteLine("mam W");
            DataTable U1 = Vmatrix(Tsvd1, V1, sig1);
        }
        public DataTable SVD(DataTable dt)
        {
            for (int i = 0; i < dt.Columns.Count - 1; i++)
            {
                for (int j = 0; j < dt.Rows.Count; j++)
                {
                    if (dt.Rows[j].Field<string>(i) == "?")
                    {
                        DataTable svd1 = new DataTable();
                        DataTable svd2 = new DataTable();
                        for (int i2 = 0; i2 < dt.Columns.Count; i2++)
                        {
                            svd1.Columns.Add(i2.ToString());
                        }
                        for (int j2 = 0; j2 < dt.Rows.Count; j2++)
                        {
                            if (j2 != j)
                            {
                                string[] tab = new string[dt.Columns.Count];
                                for (int x = 0; x < dt.Columns.Count; x++)
                                {
                                    tab[x] = dt.Rows[j2].Field<string>(x);
                                }
                                svd1.Rows.Add(tab);
                            }

                        }
                        for (int i2 = 0; i2 < dt.Columns.Count; i2++)
                        {
                            if (i2 != i)
                            {
                                svd2.Columns.Add(i2.ToString());
                            }
                        }

                        for (int j2 = 0; j2 < dt.Rows.Count; j2++)
                        {
                            string[] tab = new string[dt.Columns.Count - 1];
                            int x2 = 0;
                            for (int x = 0; x < dt.Columns.Count; x++)
                            {
                                if (x != i)
                                {
                                    tab[x2] = dt.Rows[j2].Field<string>(x);
                                    x2++;
                                }
                            }
                            svd2.Rows.Add(tab);
                        }
                        for (int i3 = 0; i3 < svd1.Columns.Count - 1; i3++)
                        {
                            for (int j3 = 0; j3 < svd1.Rows.Count; j3++)
                            {
                                if (svd1.Rows[j3].Field<string>(i3) == "?")
                                {
                                    svd1.Rows[j3].SetField<string>(i3, this.Abs2(svd1.Columns.Count - 1, svd1, j3, i3).ToString());
                                    Console.WriteLine(" svd1: " + this.Abs2(svd1.Columns.Count - 1, svd1, j3, i3).ToString());
                                }
                            }
                        }
                        for (int i3 = 0; i3 < svd2.Columns.Count - 1; i3++)
                        {
                            for (int j3 = 0; j3 < svd2.Rows.Count; j3++)
                            {
                                if (svd2.Rows[j3].Field<string>(i3) == "?")
                                {
                                    svd2.Rows[j3].SetField<string>(i3, this.Abs2(svd2.Columns.Count - 1, svd1, j3, i3).ToString());
                                }
                            }
                        }
                        svd1.Columns.RemoveAt(svd1.Columns.Count - 1);
                        svd2.Columns.RemoveAt(svd2.Columns.Count - 1);
                        Console.WriteLine("usunalem kolumny");
                        DataTable Tsvd1 = this.Transponowanie(svd1);
                        DataTable Tsvd2 = this.Transponowanie(svd2);
                        Console.WriteLine("po transponowaniu");
                        DataTable B1dt = this.MnożenieMacierzy(Tsvd1, svd1);
                        DataTable B1dt2 = this.MnożenieMacierzy(svd1, Tsvd1);
                        int st1 = this.StopienMacierzy(B1dt);
                        int st1t = this.StopienMacierzy(B1dt2);
                        if ( st1>st1t )
                        {
                            B1dt = B1dt2;
                        }
                        else if (st1 == st1t && B1dt2.Rows.Count<B1dt.Rows.Count)
                        {
                            B1dt = B1dt2;
                        }
                        DataTable B2dt = this.MnożenieMacierzy(Tsvd2, svd2);
                        DataTable B2dt2 = this.MnożenieMacierzy(svd2, Tsvd2);
                        int st2 = this.StopienMacierzy(B2dt);
                        int st2t =this.StopienMacierzy(B2dt2); 
                        if ( st2> st2t)
                        {
                            B2dt = B2dt2;
                        }
                        else if (st2 == st2t && B2dt2.Rows.Count < B2dt.Rows.Count)
                        {
                            B2dt = B2dt2;
                        }
                        Console.WriteLine("mam juz b");
                        DataTable l1dt = this.wartWlasneMac(B1dt);
                        DataTable l2dt = this.wartWlasneMac(B2dt);
                        Console.WriteLine("mam juz wartosci wlasne");
                        DataTable V1 = this.Uatrix(B1dt);
                        DataTable V2 = this.Uatrix(B2dt);
                        Console.WriteLine("mam juz V");
                        DataTable sig1 = this.sqrtWartWlas(l1dt);
                        DataTable sig2 = this.sqrtWartWlas(l2dt);
                        Console.WriteLine("mama sigmy");
                        DataTable W1 = sig1;
                        DataTable W2 = sig2;
                        Console.WriteLine("mam W");
                        DataTable U1 = Vmatrix(svd1, V1, sig1);
                        DataTable U2 = Vmatrix(svd2, V2, sig2);
                        Console.WriteLine("Mam U");
                        double suma = 0;
                        int t = 0;
                        for (int z = 0; z < svd2.Columns.Count; z++)
                        {
                            double naw1 = double.Parse(V2.Rows[i].Field<string>(t)) * Math.Sqrt(double.Parse(W2.Rows[t].Field<string>(t)));
                            double naw2 = double.Parse(V1.Rows[j].Field<string>(t)) * Math.Sqrt(double.Parse(W1.Rows[t].Field<string>(t)));
                            t++;
                            suma += naw1 * naw2;
                            Console.WriteLine("wstawiłem wartość" + svd1.Rows[i].Field<string>(z));
                        }
                        dt.Rows[j].SetField<string>(i, suma.ToString());
                    }
                }
            }
            return dt;
        }

        public int StopienMacierzy(DataTable dt)
        {
            double[,] matrix = new double[dt.Rows.Count, dt.Columns.Count];

            for (int i = 0; i < dt.Rows.Count; i++)
            {
                for (int j = 0; j < dt.Columns.Count; j++)
                {
                    matrix[i, j] = double.Parse(dt.Rows[i].Field<string>(j));
                }
            }
            Double[][] d = new Double[dt.Rows.Count][];
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                double[] drow = new double[dt.Rows.Count];
                for (int j = 0; j < dt.Rows.Count; j++)
                {
                    drow[j] = matrix[i, j];
                    Console.WriteLine(matrix[i, j]);
                }
                d[i] = drow;
            }

            GeneralMatrix gmatrix = new GeneralMatrix(d);
            int rank = gmatrix.Rank();
            return rank;
        }

        public double[] OrtogonalizacjaGramaSchmidta(DataTable udt, int columnnr, int colnr2)
        {
            double[] tab1 = new double[udt.Rows.Count];
            double[] e1 = new double[udt.Rows.Count];
            for (int i = 0; i < tab1.Length; i++)
            {
                if (i == columnnr)
                {
                    tab1[i] = 1;
                    e1[i] = 1;
                }
                else
                {
                    tab1[i] = 0;
                    e1[i] = 0;
                }
            }

            for (int i = 0; i < colnr2; i++)
            {
                double[] tab2 = new double[udt.Rows.Count];
                int j = 0;
                foreach (DataRow r in udt.Rows)
                {
                    tab2[j] = double.Parse(r.Field<string>(i));
                    j++;
                }

                double nawias = MnozenieSkalarne(e1, tab2);
                for (int l = 0; l < tab2.Length; l++)
                {
                    tab2[l] *= nawias;
                }

                for (int l = 0; l < tab1.Length; l++)
                {
                    tab1[l] -= tab2[l];
                }
            }

            return tab1;
        }
        public double MnozenieSkalarne(double[] tab1, double[] tab2)
        {
            double wynik = 0;
            for (int i = 0; i < tab2.Length; i++)
            {
                wynik += tab1[i] * tab2[i];
            }
            return wynik;
        }
    }
    public class Odleglosc
    {
        public float odl;
        public int row;
        public Odleglosc(float o, int r)
        {
            odl = o;
            row = r;
        }
    }


}
